package com.hu.bgp.framework.clientapi;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamFactory;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.ServiceDefTarget;

import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.hu.bgp.framework.clientapi.util.Firebug;

/**
 * Schrijf een subklasse van deze klasse om een client (game UI) te
 * implementeren.
 * 
 * @author ejvos
 */
public abstract class Client implements FailureHandler, EntryPoint
{
	public static final String GAMEAREA_DIV_ID = "boardgamearea";
	protected static Client instance;
	protected GameID gameID;
	private BoardGameServiceAsync bgpService;
	boolean isLoaded = false;

	public final void onModuleLoad()
	{
		initJsNativeInterface();
		// get a binding to the servlet
		bgpService = GWT.create(BoardGameService.class);
		ServiceDefTarget target = (ServiceDefTarget) bgpService;
		target.setServiceEntryPoint("/bgp/games");

		// add some defautl connectin screen?...
		// final module load done by native call from the bgp container
		// TODO Debug without connection shwo widget
		onModuleLoad2();
		exportIsloaded();
		
		RootPanel rootPanel = RootPanel.get(GAMEAREA_DIV_ID);
		rootPanel.clear();
		rootPanel.add(getPlayArea());
		Firebug.debug("[GWT Boardgame Module] Complete!");
	}

	public static void isConnected(String gameID)
	{
		// TODO other stuff ?...
		Firebug.debug("isConnected(" + gameID + ")");
		instance.gameID.setGameID(gameID);
		// onModuleLoad2();
	}

	protected abstract void onModuleLoad2();

	protected abstract void handleMessage(ServerToClientMessage message);

	protected abstract Widget getPlayArea();

	protected void sendMessageAndIgnoreOutcome(ClientToServerMessage message)
	{
		message.setGameID(gameID);
		bgpService.handleMessage(message, new FailureHandlingCallback<Void>(this)
		{
			public void onSuccess(Void result)
			{
			}
		});
	}

	public static Object clientDeserializer(String encodedPayload) throws SerializationException
	{
		// Create the serialization stream factory
		SerializationStreamFactory serializationFactory = GWT.create(BoardGameService.class);

		// Create a stream reader
		SerializationStreamReader streamReader = serializationFactory.createStreamReader(encodedPayload);
		// Deserialize the instance
		return streamReader.readObject();
	}

	public static void sendRawGWTObject(String payload)
	{
		try
		{
			ServerToClientMessage x = (ServerToClientMessage) clientDeserializer(payload);
			instance.handleMessage(x);
		}
		catch (SerializationException e)
		{
			// TODO Auto-generated catch block
			Window.alert("[ERROR]" + e.getMessage() + "\n" + e.toString());
			e.printStackTrace();
		}
	}

	// TODO put native methods in bgp js namespace...
	public void initJsNativeInterface()
	{
		exportSendRawGWTObject();
		exportIsConnected();

	}

	public native void exportSendRawGWTObject() /*-{
		$wnd['bgpenv'].sendRawGWTObject =
		   $entry(@com.hu.bgp.framework.clientapi.Client::sendRawGWTObject(Ljava/lang/String;));
	}-*/;

	public native void exportIsConnected() /*-{
		$wnd['bgpenv'].isConnected =
		  $entry(@com.hu.bgp.framework.clientapi.Client::isConnected(Ljava/lang/String;));
	}-*/;

	public native void exportIsloaded() /*-{
		$wnd['bgpenv'].isLoaded = true;
	}-*/;

}
